package Runde5;

public class Test {

	public static void main (String[] args) {
		
		//------------------------- Testfaelle zu 1. -------------------------
		
		// Neuer ReplaceableTree<String> wird erstellt, zufaellige Knoten hinzugefuegt.
		ReplaceableTree<String> repS = new ReplaceableTree<String>("Wurzel");
		repS.add("Kind 1");
		repS.add("Kind 2");
		repS.add("Kind 3");
		
		//Iterator ueber den ReplacableTree, der die Elemente in levelorder ausgibt.
		TreeIter<String> repSIt = repS.iterator();
		System.out.println("Alle Elemente des ReplaceableTree<String>: ");
		while(repSIt.hasNext())
			System.out.println(repSIt.next());
		
		//Suche nach "Kind 1"
		Iter<Boolean> repSS = repS.search("Kind 1");
		System.out.println("Pfad zu Kind 1: ");
		while(repSS.hasNext())
			System.out.print(repSS.next()+" ");
		
		//contains() wird auf "Kind 1" angewandt.
		TreeIter<String> repSCon = repS.contains("Kind 1");
		System.out.println("\nTeilbaum zu Kind 1: ");
		while(repSCon.hasNext())
			System.out.println(repSCon.next());
		
		System.out.println();
		
		
		//Jetzt Test eines InorderTree<Integer> mit zufaelligen Werten.
		InorderTree<Integer> intTree = new InorderTree<Integer>(567);
		intTree.add(0);
		intTree.add(123);
		intTree.add(-144);
		intTree.add(1337);
		intTree.add(42);
		
		//Ausgabe ueber den Iterator, der die Liste mit der im Namen implizierten Traversierung benutzt.
		System.out.println("Elemente eines Integer-Inordertrees: ");
		TreeIter<Integer> intTreeIt = intTree.iterator();
		while(intTreeIt.hasNext()) {
			System.out.println(intTreeIt.next());
		}
		System.out.println();
		
		//contains() gibt jeweils auch immer den Unterbaum aus, falls der Knoten gefunden wurde.	
		System.out.println("Enthaelt der Baum die Zahl 0? (+ Subtree)");
		TreeIter<Integer> intTreeContains = intTree.contains(0);
		while (intTreeContains.hasNext()) {
			System.out.println(intTreeContains.next());
		}
		System.out.println("Enthaelt der Baum die Zahl 123? (+ Subtree)");
		intTreeContains = intTree.contains(123);
		while (intTreeContains.hasNext()) {
			System.out.println(intTreeContains.next());
		}
		System.out.println();
		
		//Und nun die SortedTree-spezifische Suche, die jedoch ebenfalls einen Iterator ueber eine Boolean-Liste, die den Pfad enthaelt, ausgibt.
		System.out.println("Suche nach der Zahl 1337: ");
		Iter<Boolean> intTreeSearch = intTree.search(1337);
		while (intTreeSearch.hasNext()) {
			System.out.println(intTreeSearch.next());
		}
		System.out.println("Suche nach der Zahl 42: ");
		intTreeSearch = intTree.search(42);
		while (intTreeSearch.hasNext()) {
			System.out.println(intTreeSearch.next());
		}
		
		//Erstellen von Testdaten fuer den PreorderTree<Student>-Baum (und den Baum selber).
		System.out.println();
		Student a = new Student("Peter Maffay", 87534);
		PreorderTree<Student> studTree = new PreorderTree<Student>(a);
		Student b = new Student("Horst Peter", 12354);
		Student c = new Student("Hans Wurst", 36875);
		Student d = new Student("Struwwel Peter", 68545);
		studTree.add(b);
		studTree.add(c);
		studTree.add(d);
		
		//Dieser Baum wird in Preorder-Reihenfolge traversiert.
		System.out.println("Elemente des Student-Preordertrees: ");
		TreeIter<Student> studTreeIt = studTree.iterator();
		while(studTreeIt.hasNext()) {
			System.out.println(studTreeIt.next());
		}
		System.out.println();
		
		//Funktionieren die Prozeduren auch auf Studenten? Hier wird contains() getestet.
		System.out.println("Enthaelt der Baum den Studenten Hans Wurst? (+ Subtree)");
		TreeIter<Student> studTreeContains = studTree.contains(c);
		while (studTreeContains.hasNext()) {
			System.out.println(studTreeContains.next());
		}
		System.out.println("Enthaelt der Baum den Studenten Struwwel Peter? (+ Subtree)");
		studTreeContains = studTree.contains(d);
		while (studTreeContains.hasNext()) {
			System.out.println(studTreeContains.next());
		}
		System.out.println();
		
		//... und hier search().
		System.out.println("Suche nach Peter Maffay: ");
		Iter<Boolean> studTreeSearch = studTree.search(a);
		while (studTreeSearch.hasNext()) {
			System.out.println(studTreeSearch.next());
		}
		System.out.println("(Falls hier nichts anderes steht, ist die Suche erfolgreich, da bei der Suche nach der Wurzel ein leerer Iterator zurueckgeliefert wird.)");
		System.out.println("Suche nach Horst Peter: ");
		studTreeSearch = studTree.search(b);
		while (studTreeSearch.hasNext()) {
			System.out.println(studTreeSearch.next());
		}
		System.out.println();
		
		//Das gleiche Spiel mit Professoren in einem PostorderTree.
		Professor e = new Professor("Barack Obama", "Jura");
		PostorderTree<Professor> profTree = new PostorderTree<Professor>(e);
		Professor f = new Professor("Gerhard Schroeder", "Petroleum Engineering");
		Professor g = new Professor("Vladimir Putin", "Military Engineering");
		Professor h = new Professor("Kim Jong Il", "Midget Science");
		profTree.add(f);
		profTree.add(g);
		profTree.add(h);
		
		//Zu guter letzt die Postorder-Traversierung.
		System.out.println("Elemente des Professor-Postordertrees: ");
		TreeIter<Professor> profTreeIt = profTree.iterator();
		while(profTreeIt.hasNext()) {
			System.out.println(profTreeIt.next());
		}
		System.out.println();
		
		//contains() funktioniert auch diesen natuerlich auf die gleiche Weise.
		System.out.println("Enthaelt der Baum den Professor Vladimir Putin? (+ Subtree)");
		TreeIter<Professor> profTreeContains = profTree.contains(g);
		while (profTreeContains.hasNext()) {
			System.out.println(profTreeContains.next());
		}
		System.out.println("Enthaelt der Baum den Professor Kim Jong Il? (+ Subtree)");
		profTreeContains = profTree.contains(h);
		while (profTreeContains.hasNext()) {
			System.out.println(profTreeContains.next());
		}
		System.out.println();
		
		//... und search() ebenso.
		System.out.println("Suche nach Barack Obama: ");
		Iter<Boolean> profTreeSearch = profTree.search(e);
		while (profTreeSearch.hasNext()) {
			System.out.println(profTreeSearch.next());
		}
		System.out.println("(Falls hier nichts anderes steht, ist die Suche erfolgreich, da bei der Suche nach der Wurzel ein leerer Iterator zurueckgeliefert wird.)");
		System.out.println("Suche nach Gerhard Schroeder: ");
		profTreeSearch = profTree.search(f);
		while (profTreeSearch.hasNext()) {
			System.out.println(profTreeSearch.next());
		}
		System.out.println();
		
		//Testfall 2.Iterator und Struktur(mit Down) Ausgabe.
		System.out.println("Erstelle ReplaceableTree<Person> und fuege diverse Stundenten und Professoren ein ...");
		ReplaceableTree<Person> rep = new ReplaceableTree<Person>(new Professor("Martin Putz","Testinstitut"));
		Student s1 = new Student("Peter Frei",2);
		Professor p1 = new Professor("Herbert Scham","Zufallsinstitut");
		rep.add(new Student("Thomas Schoen",1));
		rep.add(s1);
		rep.add(p1);
		TreeIter<Person> repIter = rep.iterator();
		//Ausgabe des Baumes (per Iterator)
		System.out.println("Levelorder-Ausgabe von repIter:");
		while(repIter.hasNext()){
			System.out.print(repIter.next() + ", ");
		}
		while(repIter.hasPrevious()) {
			repIter.previous();
		}
		
		//Einhaengen der Baeume aus Testfall 1
		System.out.println("\n\nReplace mit Baeumen aus Testfall 1 ...");
		System.out.println("Haenge studTree bei Knoten \"Peter Frei\" ein ...");
		rep.replace(rep.search(s1), studTree);
		System.out.println("Haenge profTree bei Knoten \"Herbert Scham\" ein ...");
		rep.replace(rep.search(p1), profTree);
		repIter = rep.iterator(); //Neuen (aktualisierten) Iterator anfordern (um über aktuellen Baum zu iterieren, siehe Anmerkung bei Postcondition)
		
		//Erneute Ausgabe des Baumes (nach Replace)
		System.out.println("Levelorder-Ausgabe von repIter:");
		while(repIter.hasNext()){
			System.out.print(repIter.next() + ", ");
		}
		while(repIter.hasPrevious()) {
			repIter.previous();
		}
		repIter.previous();
		
		System.out.println();
		//Andeutung der Baum-Struktur mit Hilfe iterierter anwendung von down() auf jeden "Knoten" der Liste
		System.out.println("\n---- Struktur-Andeutung durch down(): ---- ANFANG");
		System.out.println("Einfuegt wird bei uns immer zu erst moeglichst links und (wie gefordert) moeglichst nahe an der Wurzel.\n");
		while(repIter.hasNext()){
			Person p = repIter.next();
			//Durch kennen der Ausgabeform und iteratives Ausgeben von Teilbaeumen ist die Struktur des Originalbaumes erschlieszbar.
			System.out.println(p + " ist Wurzel seines eigenen Teilbaumes mit Levelorder-Ausgabe:");
			TreeIter<Person> tempIter = repIter.down();
			while(tempIter.hasNext()) {
				System.out.print(tempIter.next() + ", ");
			}
			System.out.print("\n\n");
		}
		System.out.print("---- Struktur-Andeutung durch down(): ---- ENDE\n\n");
		
		//Negativ-Testfaelle. Was passiert, wenn nach einem nicht vorhandenen Element gefragt wird?
		System.out.println("Enthaelt der Inorder-Baum die nicht vorhandene Zahl -42? (+ Subtree)");
		intTreeContains = intTree.contains(-42);
		try {
			while (intTreeContains.hasNext()) {
				System.out.println(intTreeContains.next());
			}
		} catch (NullPointerException ex) {
			//Da laut Aufgabenstellung gefordert ist, null zurueckzugeben, falls der Wert nicht enthalten ist, muss hier die NullpointerException gecatcht werden.
			//Um trotzdem das Ergebnis anzuzeigen, wird hier "null" geprintet.
			System.out.println("null");
		}
		
		//Selbe Vorgehensweise bei der Suche.
		System.out.println("Suche im Inorder-Baum nach der nicht vorhandenen Zahl -1337...");
		intTreeSearch = intTree.search(-1337);
		try {
			while (intTreeSearch.hasNext()) {
				System.out.println(intTreeSearch.next());
			}
		} catch (NullPointerException ex) {
			System.out.println("null");
		}
		
		System.out.println();
		
		//Auf Students muss das auch funktionieren, ...
		Student z = new Student("Jesus Christus", 63274);
		System.out.println("Enthaelt der PreorderTree Jesus?");
		studTreeContains = studTree.contains(z);
		try {
			while (studTreeContains.hasNext()) {
				System.out.println(studTreeContains.next());
			}
		} catch (NullPointerException ex) {
			System.out.println("null");
		}
		
		System.out.println();
		
		//... sowie auf Professoren.
		Professor y = new Professor("Jesus Christus", "Institute of Immaculate Conception");
		
		System.out.println("Suche im Postorder-Baum nach Jesus...");
		profTreeSearch = profTree.search(y);
		try {
			while (profTreeSearch.hasNext()) {
				System.out.println(profTreeSearch.next());
			}
		} catch (NullPointerException ex) {
			System.out.println("null");
		}
		
		System.out.println();
		
		//Versuch, an einer nicht vorhandenen Position zu replacen.
		System.out.println("Ersetze im Baum Position, die nicht vorhanden ist...\nBaum vor replace...");
		ReplaceableTree<String> repS2 = new ReplaceableTree<String>("Root");
		repS2.add("Child 1");
		repS2.add("Child 2");
		TreeIter<String> repS2It = repS2.iterator();
		while(repS2It.hasNext())
			System.out.println(repS2It.next());
		System.out.println("Baum nach replace...");
		List<Boolean> repS2L = new List<Boolean>();
		repS2L.add(true);
		repS2L.add(true);
		repS2L.add(true);
		repS2.replace(repS2L.iterator(), repS);
		repS2It = repS2.iterator();
		while(repS2It.hasNext())
			System.out.println(repS2It.next());
		
		
		System.out.println("Ersetze im Baum Position, wo nur Elternknoten vorhanden ist...\nBaum nach replace...");
		repS2L = new List<Boolean>();
		repS2L.add(true);
		repS2L.add(true);
		repS2.replace(repS2L.iterator(), repS);
		repS2It = repS2.iterator();
		while(repS2It.hasNext())
			System.out.println(repS2It.next());
	}
}
